home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-02
/
jed10.zip
/
VIDBLAST.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-02-26
|
10KB
|
201 lines
;===========================================================================
;
; V I D B L A S T - Blast character pattern into memory, & add attributes
;
;===========================================================================
;
; by Jeff Duntemann 25 November 1988
;
; VIDBLAST is written to be called from Turbo Pascal V4.0 or 5.0 using the
; EXTERNAL machine-code procedure convention.
;
; Declare the procedure itself as external using this declaration:
;
; PROCEDURE VidBlast(ScreenEnd,StoreEnd : ScrnPtr;
; ScreenX,ScreenY : Integer;
; ULX,ULY : Integer;
; Width,Height : Integer;
; Attribute : Byte;
; DeadLines : Integer);
; EXTERNAL;
;
; What we have here is a means of moving a rectangular region of a text
; screen (either the visible screen or a screen stored on the heap) from
; the screen array to a storage array. It is the text analog of a BITBLT
; (BIT BLock Transfer.) It is an essential component of any windowing or
; menuing system that expects to update the display faster than the eyes
; can follow.
;
; It works like this: ScreenEnd and StoreEnd are the two pointers pointing
; to the screen array and the storage array, respectively. If the destination
; pointer is NIL, VidBlast returns without taking any action. ScreenX and
; ScreenY are the dimensions of the screen in use. ULX and ULY are the
; coordinates of the upper left hand corner of the rectangular region to be
; written to on the destination screen. Width and Height are the dimensions
; of the region to be written to on the destination screen.
;
; During the blast itself, the attribute byte passed in the Attribute
; parameter is written to the screen along with the character information
; pointed to by the source pointer. In effect, this means we do a byte-sized
; read from the source character data, but a word-sized write to the screen.
;
;
; There is a critical difference between a screen array and a storage array.
; A screen array has an implied structure of rows and columns, dictated by
; the ScreenX and ScreenY parameters. A rectangular region within such an
; array is not one contiguous block of elements, but rather a number of
; blocks of elements separated by some quantity of storage not included in
; the block transfer. Additionally, the rectangular region begins at some
; offset from the beginning of the screen array. A storage buffer, by
; contrast, is a simple contiguous array of character/attribute pairs without
; any consideration for the row/column structure of a visible screen. We
; do it this way for the utmost speed and most efficient use of memory.
;
; Allocation of both screen and storage arrays, of course, is the
; responsibility of the calling logic. HINT: Use GetMem and FreeMem
; rather than New and Dispose.
;
;
; To reassemble/relink WORDBLT:
;
; Assemble this file with MASM or TASM: "C>MASM VIDBLAST;"
; (The semicolon is unnecessary with TASM.)
;
;========================
;
; STACK PROTOCOL
;
; This creature puts lots of things on the stack. Study closely:
;
ONSTACK STRUC
OLDBP DW ? ;Caller's BP value saved on the stack
RETADDR DD ? ;Full 32-bit return address. (This is a FAR proc!)
DEADLNS DW ? ;Number of lines of dead space to insert between blasted lines
ATTR DW ? ;Attribute to be added to blasted pattern
WHEIGHT DW ? ;HEIGHT OF WINDOW TO BE MOVED
WWIDTH DW ? ;WIDTH OF WINDOW TO BE MOVED
ULY DW ? ;Y COORDINATE OF UPPER LEFT CORNER OF WINDOW
ULX DW ? ;X COORDINATE OF UPPER LEFT CORNER OF WINDOW
YSIZE DW ? ;GENNED MAX Y DIMENSION OF CURRENT VISIBLE SCREEN
XSIZE DW ? ;GENNED MAX X DIMENSION OF CURRENT VISIBLE SCREEN
STORE DD ? ;32-BIT POINTER TO STORE BUFFER
SCREEN DD ? ;32-BIT POINTER TO SCREEN BUFFER
ENDMRK DB ? ;DUMMY FIELD FOR SIZE CALCULATION PURPOSES
ONSTACK ENDS
CODE SEGMENT PUBLIC
ASSUME CS:CODE
PUBLIC VIDBLAST
VIDBLAST PROC FAR
PUSH BP ;SAVE CALLER'S BP VALUE
MOV BP,SP ;SP BECOMES NEW VALUE OF BP
PUSH DS ;SAVE CALLER'S DS VALUE
;-------------------------------------------------------------------------
; The increment between window lines must be calculated and stored in DX.
; This includes adding additional instances of the increment for "dead
; space" to avoid lines between forms, things like that.
;-------------------------------------------------------------------------
MOV DX,[BP].XSIZE
SUB DX,[BP].WWIDTH ;INCREMENT IS SCREEN WIDTH MINUS
; WINDOW WIDTH
SHL DX,1 ;INCREMENT IS IN WORDS. MUST
; CONVERT TO BYTES FOR USE; HERE
; WE MULTIPLY IT BY TWO BY
; SHIFTING LEFT ONE BIT
MOV CX,[BP].DeadLns ;Put deadspace line count in CX
CMP CX,0 ;Is there any dead space needed?
JE Inset ;If not, go calculate the inset
MOV BX,[BP].XSIZE ;Mov screen width into BX
SHL BX,1 ;Multiply by two for attributes
AddDed: ADD DX,BX ;Add a screen width to increment
LOOP AddDed ;Dec CX & loop backn if CX <> 0
;-------------------------------------------------------------------------
; HERE WE CALCULATE THE INSET FROM THE START OF THE VISIBLE
; SCREEN BUFFER TO THE FIRST BYTE OF THE WINDOW TO BE BLITTED
;-------------------------------------------------------------------------
Inset: PUSH DX ;Save increment; MUL trashes DX
MOV CX,[BP].XSIZE ;SCREEN MAX X DIMENSION IN CX
MOV BX,[BP].ULX ;UL CORNER X DIMENSION IN BX
MOV AX,[BP].ULY ;UL CORNER Y DIMENSION IN AX
SUB BX,1 ;CORRECT FOR ORIGIN AT 1 NOT 0
SUB AX,1 ;CORRECT FOR ORIGIN AT 1 NOT 0
MUL CX ;MULTIPLY SCREEN WIDTH BY UL Y
ADD AX,BX ; AND ADD INDENT FROM LEFT MARGIN
MOV CX,AX
SHL CX,1
;-------------------------------------------------------------------------
; NEXT WE HAVE TO FILL THE SOURCE AND DESTINATION SEGMENT AND OFFSET
; REGISTERS, DEPENDING ON WHICH WAY DATA WILL BE FLOWING. DS:SI IS
; ALWAYS THE SOURCE ADDRESS, AND ES:DI IS ALWAYS THE DESTINATION
; ADDRESS. TOWARD DETERMINES WHETHER DATA WILL BE FLOWING TOWARD THE
; SCREEN BUFFER OR TOWARD THE STORAGE BUFFER. MUCH OF THIS CODE IS
; CHECKING TO SEE IF EITHER POINTER WAS SET TO NIL, I.E. BOTH WORDS
; SET TO ZERO. IF EITHER POINTER WAS PASSED AS NIL, WORDBLT RETURNS
; WITHOUT TAKING FURTHER ACTION.
;-------------------------------------------------------------------------
LES DI,[BP].SCREEN ;SCREEN IS DESTINATION: ES:DI
LDS SI,[BP].STORE ;STORAGE BUFFER IS SOURCE: DS:SI
MOV AX,ES ;CAN'T DO A CMP ON A SEGMENT REG.
CMP AX,0 ;A NIL POINTER IS A SEGMENT AND
JNE AddIn ; OFFSET BOTH SET TO 0
CMP DI,0 ;RETURN WITHOUT ACTING IF BOTH
JE GOHOME ; ARE SET TO 0
AddIn: ADD DI,CX ;SCREEN END MUST ADD INSET VALUE
; TO OFFSET PORTION OF POINTER
POP DX ;Restore saved increment to DX
;-------------------------------------------------------------------------
; THE POINTERS ARE NOW READY FOR WORK. NOW WE SET UP FOR THE LOOPS.
; THE DIRECTION FLAG MUST BE SET FOR AUTOINCREMENT DURING LOOPS.
;-------------------------------------------------------------------------
MOV AX,[BP].WHEIGHT ;HEIGHT IS COUNT OF LINE MOVES
MOV BX,[BP].Attr ;Move attribute byte into BX
XCHG BH,BL ;Put attribute info into high byte
;-------------------------------------------------------------------------
; DOLINE IS THE LABEL FOR THE OUTER LOOP. THIS LOOP PERFORMS HEIGHT
; STOSW OPS WHICH EACH MOVE WIDTH WORDS FROM SOURCE TO DESTINATION
;-------------------------------------------------------------------------
DOLINE: MOV CX,[BP].WWIDTH ;COUNT VALUE FOR INNER LOOP IS WIDTH
DoChar: MOV BL,[SI] ;Bring source byte into BL
MOV ES:[DI],BX ;Move WORD QUANTITY to ES:DI
INC SI ;Bump SI to next byte
INC DI ;Bump DI *by two* to next word
INC DI
LOOP DoChar ;Repeat inner loop until CX is zero
ADD DI,DX ;ADD DESTINATION INCREMENT TO DI
DEC AX ;AX IS HEIGHT; I.E. OUTER LOOP COUNTER
JNZ DOLINE ;AND LOOP UNTIL AX IS ZERO
;-------------------------------------------------------------------------
; WHEN THE OUTER LOOP IS FINISHED, THE WORK IS DONE. RESTORE REGISTERS
; AND GO HOME.
;-------------------------------------------------------------------------
GOHOME: POP DS ;RESTORE CALLER'S DS
MOV SP,BP ;RESTORE PRIOR STACK POINTER & BP
POP BP ; IN CONVENTIONAL RETURN
RET ENDMRK-RETADDR-4
VIDBLAST ENDP
CODE ENDS
END